Repository navigation
Conversation
…ogeather as a group
code-review-graph reviewOverall risk: 0.50 (MEDIUM) — 22 changed function(s)/class(es), 0 affected flow(s), 4 test gap(s) (3 with no tested caller found, 1 reached only through a caller) Risk-scored changes
Test gaps
Reached only through a callerNo test names these directly, but a tested caller reaches them along the call path shown. That is a path in the call graph, not a record of execution -- the caller's tests may never take this branch. Treat it as where to look, not as coverage: these count as gaps and are scored as untested.
Token savings: this graph-backed report used ~28,859 fewer tokens (~88%) than reading every changed file in full (estimated, chars/4 approximation). Powered by code-review-graph — local-first analysis; no code leaves the CI runner. |
|
Blocked: the Windows Job Object lifecycle is unverified, current Windows/type checks fail, and successful signal delivery is still treated as proof that the daemon stopped. In an isolated unit test, simulate a recorded running daemon and reproduce the stop defect by making |
For sure @tirth8205 I will take up the tests and update you shortly!! |
|
Yes @tirth8205 I just got your point and yet got to know that just os.kill() execution doesn't retrieve that daemon is stopped successfully correct me if I got wrong somewhere .. |
…processes get cleared
|
-> 135 daemon/watch/process tests passed, 2 skipped on Linux. |
Extract the portable CLI stop-confirmation change from PR #958 at d651370. Windows Job Object and native lifecycle changes are excluded pending validation. Retain the PID on failed or unconfirmed termination and prevent restart until the existing liveness check reports exit. Update old tests whose expectation cleared a still-live daemon PID, and add durable PID-file regressions. Co-authored-by: Tirth Kanani <tirthkanani18@gmail.com>
|
The portable stop correction from d651370 is integrated on |
yeah @tirth8205 finally all the test passed including windows daemon!! |
|
Checks pass and the code looks right. Missing: tests for the edge cases it introduces.
Every new branch in the code should have a test, including the failure branch. Disagree with any of these? Say so here first. PRs now target |
@tirth8205 facing some issues with mypy tests but yet passed all in the end!!
|
|
Gates on I mutation-checked the fifth item because it is the one that matters most. Reverting the try/except around the second On the mypy trouble in your screenshot: mypy is clean here with the exact gate command, One nit, not blocking. Queued for merge. Removing |
|
The cleanup inside Repro on the head: set Three things break at once. The original assign error is swallowed and replaced, the log handle leaks, and the exception escapes All five items from the last round are in the head and each one is individually mutation-covered. Four reverts were run, including dropping only the inner guard around the post-kill
Three Windows-only items, none blocking:
Mergeable once the terminate/kill block is guarded with a test that sets |
|
Thank you for this PR. I tested it on top of the latest staging. Before I can merge it, please fix these:
After you push the fix, I will test it again. |
|
I've addressed the requested changes:
Validation: 76 tests passed, 2 skipped. Ruff lint, the line-length check, and I've pushed the fix for re-review. |

Pull Request
Linked issue #925
Refs #925
What & why
What
Fixes Windows daemon shutdown so that watcher processes cannot remain
orphaned when
crg-daemon stopterminates the daemon before its Pythonsignal handler can run.
On Windows, watcher processes are now assigned to a standard-library
Windows Job Object configured with
JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE.This ensures that if the daemon process is terminated unexpectedly, its
watcher processes are also terminated automatically.
The existing graceful shutdown path through
WatchDaemon.stop()and_terminate_child()remains unchanged for normal shutdowns and Unixplatforms.
The stop command was also updated to preserve the daemon PID file when
both graceful and forced termination attempts fail, preventing a future
crg-daemon startfrom incorrectly creating a duplicate daemon.Why
On Windows, sending
SIGTERMwithos.kill()can terminate the daemonwithout executing its Python SIGTERM handler. This bypasses
WatchDaemon.stop(), leaving watcher processes running while the daemonPID file is removed.
Those orphaned watchers can continue accessing
graph.dband a subsequentcrg-daemon startcan create duplicate watchers for the same repository.The Job Object ties the watcher lifecycle to the daemon and prevents this
orphan-process scenario.
How it was tested
Full test suite: